from picamera2 import Picamera2
import cv2
from threading import Thread, Event
import time
import os
import logging
from datetime import datetime
import paho.mqtt.client as mqtt
from paho.mqtt.client import CallbackAPIVersion

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("VideoMonitor")

# MQTT 配置
BROKER = "120.46.12.5"
PORT = 1883
TOPIC = "camera/snapshot"
CLIENT_ID = "pi_camera"
USERNAME = "gll"
PASSWORD = "gll55555"

# MQTT 回调函数
def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code == 0:
        logger.info("Connected to MQTT broker")
    else:
        logger.error(f"Failed to connect to MQTT, reason: {reason_code}")

# 初始化 MQTT 客户端
mqtt_client = mqtt.Client(client_id=CLIENT_ID, callback_api_version=CallbackAPIVersion.VERSION2)
mqtt_client.username_pw_set(username=USERNAME, password=PASSWORD)
mqtt_client.on_connect = on_connect
mqtt_client.connect(BROKER, PORT, 60)
mqtt_client.loop_start()

class VideoMonitor:
    def __init__(self):
        self.picam2 = Picamera2()
        self.recording = False
        self.stop_event = Event()
        self.fps = 0
        self.frame_count = 0
        self.fps_start = time.time()

        # 创建存储目录
        os.makedirs("recordings", exist_ok=True)
        os.makedirs("snapshots", exist_ok=True)

    def setup_camera(self):
        """配置摄像头参数"""
        config = self.picam2.create_video_configuration(
            main={"size": (320, 320)},
            controls={"FrameRate": 30}
        )
        self.picam2.configure(config)
        self.picam2.start()
        time.sleep(2)  # 摄像头预热

    def calculate_fps(self):
        """实时计算FPS"""
        self.frame_count += 1
        elapsed = time.time() - self.fps_start
        if elapsed >= 1.0:
            self.fps = self.frame_count / elapsed
            self.frame_count = 0
            self.fps_start = time.time()

    def display_stream(self):
        """显示实时视频流"""
        while not self.stop_event.is_set():
            frame = self.picam2.capture_array("main")
            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

            # 添加OSD信息
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            cv2.putText(frame, f"FPS: {self.fps:.1f} | {timestamp}",
                       (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

            cv2.imshow("Live Monitoring", frame)
            if cv2.waitKey(1) == ord('q'):
                self.stop_event.set()

    # def record_video(self):
    #     """视频录制线程"""
    #     fourcc = cv2.VideoWriter_fourcc(*'XVID')
    #     filename = f"recordings/{datetime.now().strftime('%Y%m%d_%H%M%S')}.avi"
    #     out = cv2.VideoWriter(filename, fourcc, 30.0, (320, 320))

    #     while self.recording and not self.stop_event.is_set():
    #         frame = self.picam2.capture_array("main")
    #         frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
    #         out.write(frame)
    #         time.sleep(0.03)  # 近似30FPS

    #     out.release()
    #     logger.info(f"Recording saved: {filename}")

    def take_snapshot(self):
        """拍摄单张照片并发送到 MQTT"""
        filename = f"snapshots/{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
        frame = self.picam2.capture_array("main")
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        
        # 保存照片到本地
        cv2.imwrite(filename, frame)
        logger.info(f"Snapshot saved: {filename}")

        # 将照片转换为字节并发送到 MQTT
        ret, buffer = cv2.imencode('.jpg', frame)  # 将图像编码为 JPG 字节
        if ret:
            payload = buffer.tobytes()  # 转换为字节流
            mqtt_client.publish(TOPIC, payload, qos=1)
            logger.info(f"Snapshot sent to MQTT topic: {TOPIC}")

    def run(self):
        """主控制循环"""
        self.setup_camera()

        # 启动视频显示线程
        display_thread = Thread(target=self.display_stream, daemon=True)
        display_thread.start()

        try:
            while not self.stop_event.is_set():
                self.calculate_fps()

                key = cv2.waitKey(1)
                # if key == ord('r'):  # 开始/停止录制
                #     self.recording = not self.recording
                #     if self.recording:
                #         Thread(target=self.record_video, daemon=True).start()
                #         logger.info("Recording started")
                # elif key == ord('s'):  # 拍照并发送
                if key == ord('s'):  # 拍照并发送
                    self.take_snapshot()

        except KeyboardInterrupt:
            logger.info("Shutting down...")

        finally:
            self.stop_event.set()
            self.picam2.stop()
            cv2.destroyAllWindows()
            mqtt_client.loop_stop()
            mqtt_client.disconnect()
            logger.info("System stopped")

if __name__ == "__main__":
    monitor = VideoMonitor()
    monitor.run()
